#include "GridGui.h"

CGridGui::~CGridGui()
{
	DelObj();
	UnInit();
}

const bool CGridGui::InitCanvas(::HDC ptrHDc, const int iTop, const int iLeft, const int iWidth, const int iHeight)
{
	bool bRetVal = false;
	m_bUnFlg = false;
	DelObj();
	if (!ptrHDc) return bRetVal;
	try
	{		
		m_iTop = iTop;
		m_iLeft = iLeft;
		m_ptrMemDC = ::CreateCompatibleDC(ptrHDc);
		m_ptrBmp =::CreateCompatibleBitmap(ptrHDc, iWidth, iHeight);
		::SelectObject(m_ptrMemDC, m_ptrBmp);
		::SetBkMode(m_ptrMemDC, TRANSPARENT);
		m_bUnFlg = false;
		bRetVal = true;
	}
	catch(...)
	{
	}
	return bRetVal;
}

const void CGridGui::DelObj()
{
	::DeleteObject(m_ptrBmp);
	::DeleteDC(m_ptrMemDC);
	m_bUnFlg = true;
	return;
}

const void CGridGui::UnInit()
{
	for (auto it = m_mpCellIfno.begin(); it != m_mpCellIfno.end();)
	{
		delete it->second;
		it = m_mpCellIfno.erase(it);
	}
}


COLORREF CGridGui::GetBackgroundColor()
{
	return m_dwBackgroundColor;
}

void CGridGui::SetBackgroundColor(const COLORREF dwBackgroundColor)
{
	m_dwBackgroundColor = dwBackgroundColor;
}

void CGridGui::RefreshView(HDC ptrImgDC, const int iLeft, const int iTop, const int iWidth, const int iHeight)
{		
	_RefreshView(ptrImgDC, iLeft, iTop, iWidth, iHeight);
}

void CGridGui::_RefreshView(HDC ptrImgDC, const int iLeft, const int iTop, const int iWidth, const int iHeight)
{		
	if (m_bUnFlg) return;
	::StretchBlt(ptrImgDC, iLeft, iTop, iWidth, iHeight, m_ptrMemDC, iLeft, iTop, iWidth, iHeight, SRCCOPY);
}

void CGridGui::_DrawLine(const int iBgnRow, const int iBgnCol, const int iEndRow, const int iEndCol)
{
	ST_CELL_INFO stBgnCellInfo = {0}, stEndCellInfo = {0};
	if(!_GetCellInfo(iBgnRow, iBgnCol, stBgnCellInfo)) goto __end;
__end:
	return;
}
void CGridGui::_DrawLine(const char * pszBgnName, const char * pszEndName)
{

}

int CGridGui::GetTop()
{
	return m_iTop;
}

void CGridGui::SetTop(const int iTop)
{
	m_iTop = iTop;
}

int CGridGui::GetLeft()
{
	return m_iLeft;
}

void CGridGui::SetLeft(const int iLeft)
{
	m_iLeft = iLeft;
	return;
}

bool CGridGui::GetCellInfo(int iRow, int iCol, ST_CELL_INFO & StCellInfo)
{
	memset((void *)&StCellInfo, 0, sizeof(ST_CELL_INFO));
	ST_CELL_INFO * ptrRetVal = _GetCellInfo(iRow, iCol);
	if (!ptrRetVal) return false;
	memcpy((void *)&StCellInfo, (void *)ptrRetVal, sizeof(ST_CELL_INFO));
	return true;
}

bool CGridGui::GetCellInfo(const char * pszName, ST_CELL_INFO & StCellInfo)
{
	bool bRetVal = _GetCellInfo(pszName, StCellInfo);
	return bRetVal;
}

bool CGridGui::_GetCellInfo(const char * pszName, ST_CELL_INFO & StCellInfo)
{
	bool bRetVal = false;
	ST_CELL_INFO * ptrCellInfo = NULL;
	memset((void *)&StCellInfo, 0, sizeof(ST_CELL_INFO));
	auto it = m_mpFieldInfo.find(pszName);
	if (it == m_mpFieldInfo.end()) goto __end;
	ptrCellInfo = m_mpCellIfno[it->second];
	if (!ptrCellInfo) goto __end;
	memcpy((void *)&StCellInfo, (void *)ptrCellInfo, sizeof(ST_CELL_INFO));
	bRetVal = true;
__end:
	return bRetVal;
}

bool CGridGui::_GetCellInfo(int iRow, int iCol, ST_CELL_INFO & StCellInfo)
{
	bool bRetVal = false;
	memset((void *)&StCellInfo, 0, sizeof(ST_CELL_INFO));
	ST_CELL_INFO * ptrCellInfo = _GetCellInfo(iRow, iCol);
	bRetVal = ptrCellInfo != NULL;
	if (!bRetVal) goto __end;	
	memcpy((void *)&StCellInfo, (void *)ptrCellInfo, sizeof(ST_CELL_INFO));
__end:
	return bRetVal;
}

ST_CELL_INFO * CGridGui::_GetCellInfo(int iRow, int iCol)
{
	ST_CELL_INFO * ptrRetVal = NULL;
	char szRow[22 + 1] = {0}, szCol[22 + 1] = {0};
	itoa(iRow, szRow, 10), itoa(iCol, szCol, 10);
	std::string strKey(szRow + string("_") + string(szCol));
	auto it = m_mpCellIfno.find(strKey);
	if (it == m_mpCellIfno.end()) goto __end;
	else ptrRetVal = it->second;
__end:
	return ptrRetVal;
}

int CGridGui::GetCellPos(int iRow, const int iCol, const int iLeft, const int iTop, ST_CELL_INFO & StCellInfo)
{
	int iRetVal = 0;
	//if (m_bUnFlg) goto __end;
	ST_CELL_INFO * ptrCellInfo = NULL;
	int iCurCol = iCol - 1;
	int iCurRow = iRow - 1;
	if (iRow == 0 && iCol == 0) goto __end;
	else
	{
		do 
		{
			ptrCellInfo = _GetCellInfo(iRow, iCurCol);
			if (!ptrCellInfo) iCurCol--;
		} while ((ptrCellInfo == NULL) && (iCurCol >= 0));
		if (!ptrCellInfo)
		{
			do 
			{
				ptrCellInfo = _GetCellInfo(iCurRow, iCol);
				if (!ptrCellInfo) iCurRow--;
			} while ((ptrCellInfo == NULL) && (iCurRow >= 0));
			StCellInfo.iTop += ptrCellInfo->iTop + ptrCellInfo->iHeight + StCellInfo.iRowSpace; //
			StCellInfo.iLeft += ptrCellInfo->iLeft;
		}
		else
		{
			StCellInfo.iTop += ptrCellInfo->iTop;
			StCellInfo.iLeft += ptrCellInfo->iLeft + ptrCellInfo->iWidth + StCellInfo.iColSpace;
		}		
	}
__end:
	return iRetVal;
}

void CGridGui::InitCell(const int iRow, const int iCol, const int iWidth, const int iHeight,  const char * pszName, 
				  const int iLeft, const int iTop, const int iRowSpace, const int iColSpace, int iAlign, 
				  int iFontSize, const char * pszFontName)
{
  if (iRow < 0) return;
  if (iCol < 0) return;
  if (iWidth <= 0) return;
  if (iHeight <= 0) return;
  if (_GetCellInfo(iRow, iCol)) return;
  if (iFontSize <= 0) iFontSize = TEXT_FONT_SIZE;
  if (pszFontName == NULL || pszFontName[0] == 0) pszFontName = TEXT_FONT_NAME;
  if (iAlign < 0 || iAlign > 2) iAlign = 0;
  char szRow[23] = {0}, szCol[23] = {0};
  itoa(iRow, szRow, 10); itoa(iCol, szCol, 10);
  string strPos(szRow + string("_") + szCol);
  ST_CELL_INFO * ptrCellInfo = new ST_CELL_INFO;
  m_mpCellIfno[strPos] = ptrCellInfo;
  memset((void *)ptrCellInfo, 0, sizeof(ST_CELL_INFO));
  memcpy((void *)ptrCellInfo->szName, (void *)pszName, strlen(pszName));
  memcpy((void *)ptrCellInfo->szFontName, (void *)pszFontName, strlen(pszFontName));
  ptrCellInfo->iWidth = iWidth - iColSpace;
  ptrCellInfo->iHeight = iHeight - iRowSpace;
  ptrCellInfo->iRowSpace = iRowSpace;
  ptrCellInfo->iColSpace = iColSpace;
  ptrCellInfo->iAlign = iAlign;
  ptrCellInfo->iFontSize = iFontSize;
  ptrCellInfo->iLeft = iLeft;
  ptrCellInfo->iTop = iTop;
  GetCellPos(iRow, iCol, iLeft, iTop, *ptrCellInfo);
  m_mpFieldInfo[pszName] = strPos;
}

void CGridGui::DrawCell(const char * pszName, const char * pszValue, const COLORREF dwFontColor, const COLORREF dwBackgroundColor, bool bDraLine)
{
	_DrawCell(pszName, pszValue, dwFontColor, dwBackgroundColor, bDraLine);
}

void CGridGui::_DrawCell(const char * pszName, const char * pszValue, const COLORREF dwFontColor, const COLORREF dwBackgroundColor, bool bDraLine)
{
	if (m_bUnFlg) return;
	RECT clRect;
	auto it = m_mpFieldInfo.find(pszName);
	if (it == m_mpFieldInfo.end()) return;
	int iPos = it->second.find("_", 0);
	int iRow = atoi(it->second.substr(0, iPos).c_str());
	int iCol = atoi(it->second.substr(iPos + 1, it->second.length()).c_str());
	ST_CELL_INFO * ptrCellInfo = _GetCellInfo(iRow, iCol);
	if (!ptrCellInfo) return;
	memset((void *)ptrCellInfo->szValue, 0, sizeof(ptrCellInfo->szValue));
	memcpy((void *)ptrCellInfo->szValue, (void *)pszValue, strlen(pszValue));
	if (bDraLine) InitRect(ptrCellInfo->iLeft + ptrCellInfo->iColSpace, ptrCellInfo->iTop + ptrCellInfo->iRowSpace, ptrCellInfo->iWidth - 2 * ptrCellInfo->iColSpace, ptrCellInfo->iHeight - ptrCellInfo->iRowSpace, clRect);
	else InitRect(ptrCellInfo->iLeft, ptrCellInfo->iTop, ptrCellInfo->iWidth, ptrCellInfo->iHeight, clRect);
	HFONT clFont = CreateFontA(ptrCellInfo->iFontSize, 0, 0, 0, FW_THIN, 0, 0, 0,
		GB2312_CHARSET,OUT_CHARACTER_PRECIS,CLIP_CHARACTER_PRECIS,DEFAULT_QUALITY,
		FF_MODERN, ptrCellInfo->szFontName);
	_FillColor(clRect, dwBackgroundColor); 
	HFONT *ptrOldFont = (HFONT *)SelectObject(m_ptrMemDC, clFont);
	SetTextColor(m_ptrMemDC, dwFontColor);
	clRect.top += (ptrCellInfo->iHeight - ptrCellInfo->iRowSpace - ptrCellInfo->iFontSize) / 2;
	
	if (ptrCellInfo->iAlign == 0) DrawTextA(m_ptrMemDC, pszValue, strlen(pszValue), &clRect, DT_LEFT);
	else if (ptrCellInfo->iAlign == 1) DrawTextA(m_ptrMemDC, pszValue, strlen(pszValue), &clRect, DT_CENTER || DT_SINGLELINE || DT_VCENTER);
	else if (ptrCellInfo->iAlign == 2) DrawTextA(m_ptrMemDC, pszValue, strlen(pszValue), &clRect, DT_RIGHT);
	SelectObject(m_ptrMemDC, ptrOldFont);
	DeleteObject(clFont);
}

void CGridGui::DrawCellBorder(const int iRow, const int iCol, const int iPenWidth, const COLORREF dwColor)
{
	return _DrawCellBorder(iRow, iCol, iPenWidth, dwColor);
}

void CGridGui::FillColor(::RECT & refRect, const COLORREF dwColor)
{
	_FillColor(refRect, dwColor);
}

void CGridGui::FillColor(const int iRow, const int iCol, const COLORREF dwColor)
{
	_FillColor(iRow, iCol, dwColor);
}

void CGridGui::_FillColor(::RECT & refRect, const COLORREF dwColor)
{
	if (m_bUnFlg) return;
	HBRUSH clBrush = CreateSolidBrush(dwColor);
	HBRUSH ptrOldBrush = (HBRUSH)SelectObject(m_ptrMemDC, clBrush);
	FillRect(m_ptrMemDC, &refRect, clBrush);
	SelectObject(m_ptrMemDC, ptrOldBrush);
	DeleteObject(clBrush);
}

void CGridGui::_FillColor(const int iRow, const int iCol, const COLORREF dwColor)
{
	if (m_bUnFlg) return;
	RECT clRect;
	ST_CELL_INFO * ptrCellInfo = _GetCellInfo(iRow, iCol);
	if (!ptrCellInfo) return;
	InitRect(ptrCellInfo->iLeft, ptrCellInfo->iTop, ptrCellInfo->iWidth, ptrCellInfo->iHeight, clRect);
	_FillColor(clRect, dwColor);
}

void CGridGui::_DrawCellBorder(const int iRow, const int iCol, const int iPenWidth, const COLORREF dwColor)
{
	if (m_bUnFlg) return;
	RECT clCellBorderRect;
	ST_CELL_INFO * ptrCellInfo = _GetCellInfo(iRow, iCol);
	if (!ptrCellInfo) return;
	InitRect(ptrCellInfo->iLeft, ptrCellInfo->iTop, ptrCellInfo->iWidth, ptrCellInfo->iHeight, clCellBorderRect);	
	HPEN clPen = CreatePen(PS_SOLID, iPenWidth, dwColor);
	HPEN * ptrOldPen = (HPEN *)SelectObject(m_ptrMemDC, clPen);
	Rectangle(m_ptrMemDC, clCellBorderRect.left, clCellBorderRect.top, clCellBorderRect.right - clCellBorderRect.left, clCellBorderRect.bottom - clCellBorderRect.top);
	SelectObject(m_ptrMemDC, ptrOldPen);
	DeleteObject(clPen);
}

void CGridGui::InitRect(const int iLeft, const int iTop, const int iWidth, const int iHeight, RECT & refRect)
{
	refRect.left = iLeft;
	refRect.top = iTop;
	refRect.right = iLeft + iWidth;
	refRect.bottom = iTop + iHeight;
}